package whf.framework.resource.thread;

import java.util.Iterator;
import java.util.List;

import whf.framework.log.Log;
import whf.framework.log.LogFactory;
import whf.framework.util.Utils;

/**
 * 线程池
 * @author wanghaifeng
 * @create Oct 28, 2006 11:34:05 PM
 * 
 */
public class ThreadPool extends Thread {
	private static Log log = LogFactory.getLog(ThreadPool.class);
	
	private static final int DEFAULT_POOL_SIZE = 10;
	
	private int poolSize = 10;
	
	private long threadIndex = 0;
	
	private long poolCheckCount;
	
	/**
	 * 每隔一段时间检查一次线程数量
	 */
	private final static long CHECK_INTERVAL = 100;
	
	private List<AbstractPoolableThread> threadsCache = Utils.newArrayList();
	
	/**
	 * 线程缓冲池
	 */
	private List<AbstractPoolableThread> waittingThreads = Utils.newArrayList();
	
	/**
	 * 当前正在执行的线程
	 */
	private List<AbstractPoolableThread> runningThreads = Utils.newArrayList();
	
	// 缺省单例
	private static ThreadPool defaultInstance = null;
	
	public static ThreadPool getDefaultInstance(){
		if(defaultInstance == null) {
			defaultInstance = new ThreadPool();
			defaultInstance.start();
		}
		return defaultInstance;
	}
	
	public ThreadPool(){
		this.poolSize = DEFAULT_POOL_SIZE;
	}
	
	public ThreadPool(int poolSize){
		this.poolSize = poolSize;
	}
	
	public void addThread(AbstractPoolableThread thread){
		if(thread == null) return;
		threadIndex ++;
		thread.setName("Thread-"+threadIndex);
		this.threadsCache.add(thread);
	}
	
	public int getThreadsCount(){
		return this.waittingThreads.size();
	}
	
	@Override
	public void run(){
		log.debug("ThreadPool starting ... ");
		while(true){
			this.poolCheckCount ++;
			try{
				int runningThreadCount = 0;
				try{
					//删除非活动线程数
					Iterator<AbstractPoolableThread> runningThreadsIterator = runningThreads.iterator();
					for(; runningThreadsIterator.hasNext(); ){
						AbstractPoolableThread thread = (AbstractPoolableThread)runningThreadsIterator.next();
						if(thread.getState() == Thread.State.TERMINATED){
							runningThreadsIterator.remove();
						} else if(thread.isTimeout()){
							try{
								thread.onTimeout();
								thread.join(0);//超时,立即终止
							} catch(Exception e) {
								log.debug(this, e);
							}
							runningThreadsIterator.remove();
						}
					}
					runningThreadCount = runningThreads.size();
					//如果活动线程数小于定义的线程池大小,激活线程
					if(runningThreadCount < poolSize){
						Iterator<AbstractPoolableThread> threadsIterator = waittingThreads.iterator();
						while(threadsIterator.hasNext()){
							AbstractPoolableThread handle = (AbstractPoolableThread)threadsIterator.next();
							if(handle == null) {
								threadsIterator.remove();
								continue;
							}
							if(handle.getState() == Thread.State.NEW){
								handle.start();
								runningThreads.add(handle);
								threadsIterator.remove();
							}
							runningThreadCount ++;
							if(runningThreadCount >= poolSize){
								break;
							}
						}
					}
				}catch(Exception e){
					log.error(this, e);
				}
//				if(this.poolCheckCount % 5 == 0){
//					runningThreadCount = this.runningThreads.size();
//					int waitingThreadCount = this.waittingThreads.size()+ this.threadsCache.size();
//					log.debug("当前活动线程数:"+ runningThreadCount+"\t等待线程数:"+ waitingThreadCount);
//				}
				//在threads的空闲时间将cache中的线程全部加入threads,并清空cache
				if(this.poolCheckCount % 5 == 0){
					synchronized(this.threadsCache){
						this.waittingThreads.addAll(this.threadsCache);
						this.threadsCache.clear();
					}
				}
				Thread.sleep(CHECK_INTERVAL);
			}catch(Exception e){
				log.error(this, e);
				continue;
			}
		}
	}
	
	static class TestThread extends AbstractPoolableThread{
		private static int count = 0;
		
		public TestThread() {
		}
		
		/* (non-Javadoc)
		 * @see java.lang.Thread#run()
		 */
		@Override
		public void run() {
			count ++;
			System.out.println(count);
		}

		public void onTimeout() {
			System.out.println(count);
		}
	}
	
	public static void main(String[] args) {
		for(int i=0; i < 100; i ++) {
			ThreadPool.getDefaultInstance().addThread(new TestThread());
		}
	}
}
